﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using SalesSys.Comm.DAL;

namespace SalesSys.DAL.Base
{
    public interface IEFRepositoryBase
    {
         EFContextWarpBase EFContext { get; }
    }
    /// <summary>
    ///     EntityFramework仓储操作基类
    /// </summary>
    /// <typeparam name="TEntity">动态实体类型</typeparam>
    /// <typeparam name="TContext"></typeparam>
    public abstract class EFRepositoryBase<TEntity, TContext> :IEFRepositoryBase, IRepository<TEntity>
        where TEntity : class, IDbEntity
        where TContext : EFContextWarpBase, new()
    {

        //public EFRepositoryBase(UnitOfWorkContextBase context)
        //{
        //    efContext = context;
        //}
        protected EFContextWarpBase efContext;
        #region 属性


        /// <summary>
        ///     获取 EntityFramework的数据仓储上下文
        /// </summary>
      virtual internal protected EFContextWarpBase EFContext
        {
            get
            {
                if (efContext == null)
                    throw new NullReferenceException("数据上下文EFContext为空，请检查工作单元上下文UnitContext是否赋值");
                return efContext;
            }
         private   set
            {
                efContext = value;
            }
        }
       EFContextWarpBase IEFRepositoryBase.EFContext
       {
           get {return EFContext; }
       }
        public IQueryable<TEntity> QueryByWhere(IEnumerable<SqlItem> condition)
        {
            EqlConditionAdapter ea = new EqlConditionAdapter();
            var ep = ea.ToWhere(condition);
            return EFContext.CreateQuerySet<TEntity>().Where(ep.Key, ep.Value.ToArray());
        }
        public IQueryable<TEntity> QueryByWhere(IEnumerable<SqlItem> condition, int pageIndex, int pageSize,
            KeyValuePair<string, ListSortDirection>[] sortConditions)
        {
            if (pageIndex < 1 || pageSize < 1 || sortConditions == null || sortConditions.Length < 1)
                throw new ArgumentException("错误的分页参数");
            if (condition == null || condition.Count() < 1)
            {
                var ord = EqlConditionAdapter.ToOrderBy(sortConditions);
                var where = EFContext.CreateQuerySet<TEntity>();
                return where.Skip(ord, ((pageIndex - 1) * pageSize).ToString()).Top(pageSize.ToString());
            }
            else
            {
                EqlConditionAdapter ea = new EqlConditionAdapter();
                var ep = ea.ToWhere(condition);
                var ord = EqlConditionAdapter.ToOrderBy(sortConditions);
                var where = EFContext.CreateQuerySet<TEntity>().Where(ep.Key, ep.Value.ToArray());
                return where.Skip(ord, ((pageIndex - 1) * pageSize).ToString()).Top(pageSize.ToString());
            }
        }
        public IQueryable<TEntity> QueryByWhere(IEnumerable<SqlItem> condition, out int total, int pageIndex, int pageSize,
            KeyValuePair<string, ListSortDirection>[] sortConditions)
        {
            ObjectQuery<TEntity> where = EFContext.CreateQuerySet<TEntity>();
            if (condition != null && condition.Count() > 0)
            {
                EqlConditionAdapter ea = new EqlConditionAdapter();
                var ep = ea.ToWhere(condition);
                where = where.Where(ep.Key, ep.Value.ToArray());
            }
            total = where.Count();
            var ord = EqlConditionAdapter.ToOrderBy(sortConditions);
            return where.Skip(ord, ((pageIndex - 1) * pageSize).ToString()).Top(pageSize.ToString());
        }
        /// <summary>
        ///     获取 当前实体的查询数据集
        /// </summary>
        public virtual IQueryable<TEntity> Entities
        {
            get { return EFContext.Set<TEntity>(); }
        }

        #endregion

        #region 公共方法
        public virtual IQueryable<TEntity> EntitiesAsNoTracking(IQueryable<TEntity> entities = null)
        {
            if (entities == null)
            {
                return EFContext.Set<TEntity>().AsNoTracking();
            }
            else
            {
                return entities.AsNoTracking();
            }
        }
        public ObjectQuery<T> CreateQuery<T>(string ESQL, params ObjectParameter[] parameters)
        { 
            return EFContext.CreateQuery<T>(ESQL, parameters);
        }

        /// <summary>
        /// 执行sql命令
        /// </summary>
        /// <param name="sqlCmd"></param>
        /// <returns></returns>
        protected int ExeSqlCmd(ISqlTextCmd sqlCmd)
        {
            return EFContext.ExeSqlCommand(sqlCmd.SqlTextInfo.SqlStr, sqlCmd.GetParamArray()); 
        }

        protected DataTable  ExeSqlQuery(string sql, params DbParameter[] parameters)
        {

            return EFContext.SqlQuery(sql, parameters);
        }

        /// <summary>
        /// 执行sql查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sqlCmd"></param>
        /// <returns></returns>
        protected IEnumerable<T> ExeSqlQuery<T>(ISqlTextCmd sqlCmd)
        {
            return EFContext.ExeSqlQuery<T>(sqlCmd.SqlTextInfo.SqlStr, sqlCmd.GetParamArray());
        }
        protected IEnumerable ExeSqlQuery(Type type, ISqlTextCmd sqlCmd)
        {
            return EFContext.ExeSqlQuery(type, sqlCmd.SqlTextInfo.SqlStr, sqlCmd.GetParamArray());
        }

        /// <summary>
        ///     插入实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Insert(TEntity entity, bool isSave = true)
        {
            EFContext.RegisterNew<TEntity>(entity);
            return isSave ? EFContext.Commit() : 0;
        }

        /// <summary>
        ///     批量插入实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Insert(IEnumerable<TEntity> entities, bool isSave = true)
        {
            EFContext.RegisterNew<TEntity>(entities);
            return isSave ? EFContext.Commit() : 0;
        }

        /// <summary>
        ///     删除指定编号的记录
        /// </summary>
        /// <param name="id"> 实体记录编号 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(object id, bool isSave = true)
        {

            TEntity entity = EFContext.Set<TEntity>().Find(id);
            return entity != null ? Delete(entity, isSave) : 0;
        }
        public virtual int Delete(object[] keyValues, bool isSave = true)
        {
            TEntity entity = EFContext.Set<TEntity>().Find(keyValues);
            return entity != null ? Delete(entity, isSave) : 0;
        }
        /// <summary>
        ///     删除实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(TEntity entity, bool isSave = true)
        {
            EFContext.RegisterDeleted<TEntity>(entity);
            return isSave ? EFContext.Commit() : 0;
        }

        /// <summary>
        ///     删除实体记录集合
        /// </summary>
        /// <param name="entities"> 实体记录集合 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(IEnumerable<TEntity> entities, bool isSave = true)
        {

            EFContext.RegisterDeleted<TEntity>(entities);
            return isSave ? EFContext.Commit() : 0;
        }

        /// <summary>
        ///     删除所有符合特定表达式的数据
        /// </summary>
        /// <param name="predicate"> 查询条件谓语表达式 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Delete(Expression<Func<TEntity, bool>> predicate, bool isSave = true)
        {

            List<TEntity> entities = EFContext.Set<TEntity>().Where(predicate).ToList();
            return entities.Count > 0 ? Delete(entities, isSave) : 0;
        }

        /// <summary>
        ///     更新实体记录
        /// </summary>
        /// <param name="entity"> 实体对象 </param>
        /// <param name="isSave"> 是否执行保存 </param>
        /// <returns> 操作影响的行数 </returns>
        public virtual int Update(TEntity entity, bool isSave = true)
        {

            EFContext.RegisterModified<TEntity>(entity);
            return isSave ? EFContext.Commit() : 0;
        }
        public virtual int Update(TEntity[] entitys, bool isSave = true)
        {
            EFContext.RegisterModified<TEntity>(entitys);
            return isSave ? EFContext.Commit() : 0;
        }

        /// <summary>
        ///     查找指定主键的实体记录
        /// </summary>
        /// <param name="key"> 指定主键 </param>
        /// <returns> 符合编号的记录，不存在返回null </returns>
        public virtual TEntity Find(params object[] keyValues)
        {

            return EFContext.Set<TEntity>().Find(keyValues);
        }

        protected virtual DbSqlQuery<TEntity> SqlQuery(string sql, params object[] parameters)
        {
            return EFContext.Set<TEntity>().SqlQuery(sql, parameters);
        }


        #endregion

        #region UnitWork
             
        /// <summary>
        /// 上下文数据标记，内部使用
        /// </summary>
        internal readonly string dbContextSign = "_UnitOfWorkContext_" + typeof(TContext);
        IUnitContext unitContext;

        /// <summary>
        /// 设置上下文
        /// </summary>
        public IUnitContext UnitContext
        {
            get
            {
                return unitContext;
            }
            set
            {
                if (unitContext != null)
                {
                    throw new InvalidOperationException("当前上下文不允许重复设置！");
                }
                if (value == null)
                {
                    return;
                }
                //检查上下文
                if (value.ContextItem == null)
                    throw new ArgumentException("单元上下文数据为空","UnitContext.ContextItem");
                else
                {
                    object contextData = null;
                    value.ContextItem.TryGetValue(dbContextSign, out contextData);
                    EFContextWarpBase context = null;
                    if (contextData == null)
                    {
                        context = new TContext();
                        value.ContextItem[dbContextSign] = context;
                        value.Complete += () => context.Commit();
                    }
                    else
                    {
                        context = value.ContextItem[dbContextSign] as EFContextWarpBase;
                        if (context == null)
                            throw new ArgumentException("无法处理的单元上下文类型", "UnitContext.ContextItem[\"_UnitOfWorkContextBase\"]");
                    }
                    EFContext = context;
                    unitContext = value;
                }
            }
        }
        #endregion

    
    }

    //public abstract class TreeRepositoryBase<TEntity, TContext> : ITreeRepository<TEntity> where TEntity : class, ITreeEntity where TContext : EFContextWarpBase, new()
    //{
    //}
}
